﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ST.Buz.Base;
using ST.Buz.Base.Entity;
using ST.Buz.Base.ViewModel;
using ST.Common.Data;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Common.Util.Mvc;
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;

namespace ST.Buz.Service
{
	public partial interface IServiceSysModuleService
	{
		/// <summary>
		/// 获取模块详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		Sys_ModuleService GetViewDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取模块详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		Sys_ModuleService GetEditDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 生成模块编码
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		string GenCode(UserSession sessionCurrent);

		/// <summary>
		/// 通过编号查询模块信息
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		Sys_ModuleService GetByCode(string code);

		/// <summary>
		/// 删除模块
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		bool Delete(int id, UserSession sessionCurrent);

		/// <summary>
		/// 批量删除模块
		/// </summary>
		/// <returns></returns>
		bool BatchDelete(int[] ids, UserSession sessionCurrent);

		/// <summary>
		/// 保存排序
		/// </summary>
		/// <returns></returns>
		bool SaveSort(int[] ids, UserSession sessionCurrent);

		/// <summary>
		/// 检验模块编码是否可用
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		bool ValidateCode(int id, string code, UserSession sessionCurrent);

		/// <summary>
		/// 分页列表
		/// </summary>
		PageData GetPageList(VMS_Sys_ModuleService searchModel);

		/// <summary>
		/// 新增或修改保存
		/// </summary>
		int AddOrUpdate(Sys_ModuleService model, UserSession sessionCurrent);
	}

	public partial class ServiceSysModuleService
	{
		private readonly IServiceSysLog serviceSysLog;

		public ServiceSysModuleService(BuzContext ctx,
			IServiceSysLog _serviceSysLog,
			ILogger<ServiceSysModuleService> log)
		{
			serviceSysLog = _serviceSysLog;

			context = ctx;
			logger = log;
		}

		/// <summary>
		/// 获取查看时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public Sys_ModuleService GetViewDetail(int id, UserSession sessionCurrent)
		{
			Sys_ModuleService model = null;
			try
			{
				var results = (from s in context.SysModuleService
							   join p in context.SysModuleService on s.PID equals p.ID into sptmp
							   from sp in sptmp.DefaultIfEmpty()
							   join m in context.SysModule on s.ModuleID equals m.ID
							   where s.ID == id
							   select new
							   {
								   Model = s,
								   PName = sp.Name,
								   ModuleName = m.Name
							   }).AsNoTracking().ToList();
				if (results == null || results.Count == 0)
				{
					throw new BuzException("未找到相关记录");
				}
				model = results[0].Model;
				model.PName = results[0].PName;
				model.ModuleName = results[0].ModuleName;
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return model;
		}

		/// <summary>
		/// 获取编辑时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public Sys_ModuleService GetEditDetail(int id, UserSession sessionCurrent)
		{
			return GetViewDetail(id, sessionCurrent);
		}

		/// <summary>
		/// 生成模块菜单编码
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public string GenCode(UserSession sessionCurrent)
		{
			try
			{
				while (true)
				{
					string code = Guid.NewGuid().ToString("N").Substring(0, 10).ToUpper();
					if (!context.SysModuleService.Any(m => m.Code == code))
					{
						return code;
					}
				}
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "生成模块菜单编码出错");
				throw new BuzException("生成模块菜单编码失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 通过编号查询模块菜单信息
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		public Sys_ModuleService GetByCode(string code)
		{
			Sys_ModuleService model = null;
			try
			{
				if (string.IsNullOrEmpty(code))
				{
					throw new BuzException("模块菜单编码不能为空");
				}
				model = context.SysModuleService.SingleOrDefault(m => m.Code == code);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return model;
		}

		/// <summary>
		/// 删除具体操作
		/// </summary>
		/// <param name="id"></param>
		/// <param name="ip"></param>
		/// <param name="dtNow"></param>
		/// <param name="sessionCurrent"></param>
		protected void DeleteWithinTrans(int id, string ip, DateTime dtNow, UserSession sessionCurrent)
		{
			var modelOld = Get(id, true);
			if (context.SysModuleAction.Any(m => m.ServiceID == id))
			{
				throw new BuzException("该菜单下有关联的功能，请先删除菜单下的所有功能");
			}
			//todo:删除所有关联的功能
			//todo:删除所有关联的角色功能
			Delete(modelOld);

			serviceSysLog.Add(sessionCurrent, ip, $"删除模块菜单{modelOld.Name}[{modelOld.Code}]信息，原信息：", modelOld, dtNow);
		}

		/// <summary>
		/// 删除模块菜单
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool Delete(int id, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "删除模块菜单出错");
				throw new BuzException("删除模块菜单失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 批量删除模块菜单
		/// </summary>
		/// <returns></returns>
		public bool BatchDelete(int[] ids, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				if (ids == null || ids.Length == 0)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						foreach (int id in ids)
						{
							DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						}
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "批量删除模块菜单出错");
				throw new BuzException("批量删除模块菜单失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 保存排序
		/// </summary>
		/// <returns></returns>
		public bool SaveSort(int[] ids, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				if (ids == null || ids.Length == 0)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();
						int sort = 0;
						foreach (int id in ids)
						{
							SqlParameter[] paras = new SqlParameter[]{
								new SqlParameter("@True",true),
								new SqlParameter("@Sort",sort++),
								new SqlParameter("@ID",id)
							};
							context.Database.ExecuteSqlRaw("UPDATE Sys_ModuleService SET Sort = CASE Reserved WHEN @True THEN Sort ELSE @Sort END WHERE ID = @ID", paras);
						}

						serviceSysLog.Add(sessionCurrent, ip, "保存菜单排序信息，新顺序：" + string.Join(",", ids), dtNow);
						context.SaveChanges();
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存菜单排序出错");
				throw new BuzException("保存菜单排序失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 检验编码是否可用
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool ValidateCode(int id, string code, UserSession sessionCurrent)
		{
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				if (string.IsNullOrEmpty(code))
				{
					throw new BuzException("模块菜单编码不能为空");
				}
				if (id == 0)
				{
					return !context.SysModuleService.Any(m => m.Code == code);
				}
				var lst = context.SysModuleService.Where(m => m.Code == code).AsNoTracking().ToList();
				if (lst.Count == 0)
				{
					return true;
				}
				foreach (var i in lst)
				{
					if (i.ID != id)
					{
						return false;
					}
				}

				return true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "检验模块菜单编码是否可用出错");
				throw new BuzException("检验模块菜单编码是否可用失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 分页列表
		/// </summary>
		public PageData GetPageList(VMS_Sys_ModuleService searchModel)
		{
			PageData result = null;
			try
			{
				searchModel.Validate();

				var query = from u in context.SysModuleService
							select u;
				if (!string.IsNullOrWhiteSpace(searchModel.name))
				{
					query = query.Where(m => EF.Functions.Like(m.Name, "%" + searchModel.name + "%"));
				}
				if (!string.IsNullOrEmpty(searchModel.code))
				{
					query = query.Where(m => m.Code == searchModel.code);
				}
				if (searchModel.ids != null && searchModel.ids.Length > 0)
				{
					query = query.Where(m => searchModel.ids.Contains(m.ID));
				}
				if (searchModel.moduleid.HasValue)
				{
					query = query.Where(m => m.ModuleID == searchModel.moduleid.Value);
				}

				switch (searchModel.sortby)
				{
					case "Code":
						////数据库分页，不支持多表
						//query = query.OrderByDescending(e => EF.Property<object>(e, sortOrder));
						////内存分页
						////query = query.OrderByDescending(e => e.GetType().GetProperty(sortOrder).GetValue(e, null));
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Code) : query.OrderByDescending(e => e.Code);
						break;
					case "Name":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Name) : query.OrderByDescending(e => e.Name);
						break;
					case "Reserved":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Reserved) : query.OrderByDescending(e => e.Reserved);
						break;
					case "Visible":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Visible) : query.OrderByDescending(e => e.Visible);
						break;
					case "Sort":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Sort) : query.OrderByDescending(e => e.Sort);
						break;
					default:
						query = query.OrderBy(e => e.Sort).ThenBy(e => e.ID);
						break;
				}
				result = new PageData(searchModel.pnum.Value, searchModel.psize.Value);
				result.Load(query);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取分页数据出错");
				throw new BuzException("获取分页数据失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return result;
		}

		/// <summary>
		/// 新增或修改保存
		/// </summary>
		public int AddOrUpdate(Sys_ModuleService model, UserSession sessionCurrent)
		{
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				if (model == null)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						if (model.ID > 0)
						{
							if (context.SysModuleService.Any(m => m.Code == model.Code && m.ID != model.ID))
							{
								throw new BuzException("模块菜单编码重复");
							}
							Update(model);
						}
						else
						{
							if (context.SysModuleService.Any(m => m.Code == model.Code))
							{
								throw new BuzException("模块菜单编码重复");
							}
							model.AddDate = dtNow;
							model.AddManID = sessionCurrent.UserID;
							model.AddManName = sessionCurrent.UserName;
							Add(model);
						}

						#endregion

						trans.Commit();

						return model.ID;
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
				throw new BuzException("数据库保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}
	}
}